//
//  TouchDrawView.m
//  TouchTracker
//
//  Created by Rafal Rebacz on 5/14/13.
//  Copyright (c) 2013 Rafal Rebacz. All rights reserved.
//

#import "TouchDrawView.h"
#import "Line.h"

@implementation TouchDrawView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if (self)
    {
        // Initialization code
        linesInProcess = [[NSMutableDictionary alloc] init];
        completeLines = [[NSMutableArray alloc] init];
        
        [self setBackgroundColor:[UIColor whiteColor]];
        [self setMultipleTouchEnabled:YES];
        
        UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
        [self addGestureRecognizer:tapGR];
        
        UITapGestureRecognizer *doubleTapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clearLines)];
        [doubleTapGR setNumberOfTapsRequired:2];
        [self addGestureRecognizer:doubleTapGR];
        
        UILongPressGestureRecognizer *pressGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
        [self addGestureRecognizer:pressGR];
        
        panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(moveLine:)];
        panGR.delegate = self;
        panGR.cancelsTouchesInView = NO;

        [self addGestureRecognizer:panGR];
    }
    
    return self;
}

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if(gestureRecognizer == panGR)
        return YES;
    
    return NO;
}

- (void)moveLine:(UIPanGestureRecognizer *)gr
{
    if(![self selectedLine])
        return;
    
    if([gr state] == UIGestureRecognizerStateChanged)
    {
        CGPoint translation = [gr translationInView:self];
        
        CGPoint begin = [[self selectedLine] begin];
        CGPoint end = [[self selectedLine] end];
        begin.x += translation.x;
        begin.y += translation.y;
        end.x += translation.x;
        end.y += translation.y;
        
        [[self selectedLine] setBegin:begin];
        [[self selectedLine] setEnd:end];
        
        [self setNeedsDisplay];
        
        [gr setTranslation:CGPointZero inView:self];
    }
}

- (void)tap:(UIGestureRecognizer *)gr
{
    NSLog(@"Tap detected");
    
    CGPoint point = [gr locationInView:self];
    [self setSelectedLine:[self lineAtPoint:point]];
    
    // Remove processed lines to avoid creating nev line on every tap
    [linesInProcess removeAllObjects];
    
    if([self selectedLine])
    {
        [self becomeFirstResponder];
        UIMenuController *menu = [UIMenuController sharedMenuController];
        UIMenuItem *deleteItem = [[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(deleteLine:)];
        [menu setMenuItems:@[deleteItem]];
        [menu setTargetRect:CGRectMake(point.x, point.y, 2, 2) inView:self];
        [menu setMenuVisible:YES animated:YES];
        
    }
    else
        [[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES];
    
    [self setNeedsDisplay];
}

- (void)longPress:(UIGestureRecognizer *)gr
{
    if([gr state] == UIGestureRecognizerStateBegan)
    {
        CGPoint point = [gr locationInView:self];
        [self setSelectedLine:[self lineAtPoint:point]];
        
        if([self selectedLine])
        {
            [linesInProcess removeAllObjects];
        }
    }
    else if([gr state] == UIGestureRecognizerStateEnded)
    {
        [self setSelectedLine:nil];
    }
    
    [self setNeedsDisplay];
}

- (void)deleteLine:(id)sender
{
    [completeLines removeObject:[self selectedLine]];
    
    [self setNeedsDisplay];
}

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (Line *)lineAtPoint:(CGPoint)p
{
    for(Line *line in completeLines)
    {
        CGPoint start = [line begin];
        CGPoint end = [line end];
        
        for (float t = 0.0f; t < 1.0f; t += 0.05f)
        {
            float x = start.x + t * (end.x - start.x);
            float y = start.y + t * (end.y - start.y);
            
            if(hypot(x - p.x, y - p.y) < 20.0f)
            {
                return line;
            }
        }
    }
    
    return nil;
}

-(void)drawRect:(CGRect)rect
{    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineCap(context, kCGLineCapRound);
    
//    [[UIColor blackColor] set];
    for (Line *line in completeLines)
    {
        CGContextSetLineWidth(context, line.thickness);
        CGContextMoveToPoint(context, line.begin.x, line.begin.y);
        CGContextAddLineToPoint(context, line.end.x, line.end.y);
        CGContextStrokePath(context);
    }
    
    CGContextSetLineWidth(context, 10.0);
    
    [[UIColor redColor] set];
    
    for (NSValue *value in linesInProcess)
    {
        Line *line = [linesInProcess objectForKey:value];
        CGPoint vPoint = [panGR velocityInView:self];
        CGFloat velocity = (ABS(vPoint.x)+ ABS(vPoint.y))/100.0f;
        [panGR setTranslation:CGPointZero inView:self];

        line.thickness = velocity;
        
        CGContextSetLineWidth(context, line.thickness);
        CGContextMoveToPoint(context, line.begin.x, line.begin.y);
        CGContextAddLineToPoint(context, line.end.x, line.end.y);
        CGContextStrokePath(context);
//        CGContextSetLineWidth(context, 10);
    }
    
    if([self selectedLine])
    {
        [[UIColor greenColor] set];
        CGContextSetLineWidth(context, [self.selectedLine thickness]);
        CGContextMoveToPoint(context, [[self selectedLine] begin].x, [[self selectedLine] begin].y);
        CGContextAddLineToPoint(context, [[self selectedLine] end].x, [[self selectedLine] end].y);
        
        CGContextStrokePath(context);
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if([self selectedLine] != nil)
        return;
    
    for(UITouch *touch in touches)
    {
        NSValue *key = [NSValue valueWithNonretainedObject:touch];
        
        CGPoint loc = [touch locationInView:self];
        Line *newLine = [[Line alloc] init];
        [newLine setBegin:loc];
        [newLine setEnd:loc];
        
        [linesInProcess setObject:newLine forKey:key];
    }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    for(UITouch *touch in touches)
    {
        NSValue *key = [NSValue valueWithNonretainedObject:touch];
        
        Line *line = [linesInProcess objectForKey:key];
        CGPoint loc = [touch locationInView:self];
        [line setEnd:loc];
    }
    
    [self setNeedsDisplay];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self endTouches:touches];
}

-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self endTouches:touches];    
}

-(void)endTouches:(NSSet *)touches
{
    for(UITouch *touch in touches)
    {
        NSValue *key = [NSValue valueWithNonretainedObject:touch];
        
        Line *line = [linesInProcess objectForKey:key];
        
        if(line)
        {
            [completeLines addObject:line];
            [linesInProcess removeObjectForKey:key];
        }
    }
    
    [self setNeedsDisplay];
}

- (void)clearLines
{
    [linesInProcess removeAllObjects];
    [completeLines removeAllObjects];
    
    [self setNeedsDisplay];
}

@end
